package org.cnc.explain.lifecycle;

import org.cnc.explain.lifecycle.beaninstance_6.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * <p>
 * 实例化的情况
 * </p>
 *
 * @author zhiyong.tan
 * @since 2022-08-28
 */
public class Step6BeanInstance {

	@Test
	public void testMyInstantiationAwareBeanPostProcessorBeforeInstantiation(){
		// 实例化前置处理
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInstanceConfiguration.class);
		ctx.getBeanFactory().addBeanPostProcessor(new MyBeforeInstantiationAwareBeanPostProcessor());
//		ctx.register(BeanInstanceBean.class);
		BeanInstanceBean bean = ctx.getBean(BeanInstanceBean.class);
	}

	@Test
	public void testMySmartInstantiationAwareBeanPostProcessor(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInstanceConfiguration.class);
		ctx.getBeanFactory().addBeanPostProcessor(new MySmartInstantiationAwareBeanPostProcessor());
		ctx.register(BeanInstanceBean.class);
		BeanInstanceBean bean = ctx.getBean(BeanInstanceBean.class);
		System.out.println(bean);
	}

	@Test
	public void testMakeAutowireFailByUseMergedBeanDefinitionPostProcessor(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInstanceConfiguration.class);
		ctx.getBeanFactory().addBeanPostProcessor(new MyMergedBeanDefinitionPostProcessor());
		ctx.register(BeanInstanceBean.class);
		BeanInstanceBean bean = ctx.getBean(BeanInstanceBean.class);
		System.out.println(bean);
	}

	@Test
	public void testChangeFieldValueByInstantiationAwareBeanPostProcessorAfterInstantiation(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInstanceConfiguration.class);
		ctx.getBeanFactory().addBeanPostProcessor(
		new InstantiationAwareBeanPostProcessor(){
			@Override
			public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
				if("beanInstanceBean".equals(beanName)){
					BeanInstanceBean ob = (BeanInstanceBean) bean;
					ob.setBeanInstanceConstructInjectBean(
							new BeanInstanceConstructInjectBean("changed by postProcessAfterInstantiation")
					);
				}
				return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
			}
		});
		ctx.register(BeanInstanceBean.class);

		BeanInstanceBean bean = ctx.getBean(BeanInstanceBean.class);
		System.out.println(bean);
	}

	@Test
	public void testCancelFieldInjectByInstantiationAwareBeanPostProcessorAfterInstantiation(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanInstanceConfiguration.class);
		ctx.getBeanFactory().addBeanPostProcessor(
				new InstantiationAwareBeanPostProcessor(){
					@Override
					public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
						if("beanInstanceBean".equals(beanName)){
							return false;
						}
						return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
					}
				});
		ctx.register(BeanInstanceBean.class);

		BeanInstanceBean bean = ctx.getBean(BeanInstanceBean.class);
		System.out.println(bean);
	}

}
